home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / comm / term / term_source.lha / Extras / Source / term-source.lha / Translate.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  21KB  |  1,142 lines

  1. /*
  2. **    Translate.c
  3. **
  4. **    Character translation support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Translation chunk header types. */
  17.  
  18. enum    {    TYPE_NONE, TYPE_SEND, TYPE_RECEIVE };
  19.  
  20.     /* Master translation table entry types. */
  21.  
  22. enum    {    TRANSLATION_VERBATIM, TRANSLATION_IGNORE, TRANSLATION_OTHER };
  23.  
  24.     /* Symbolic names for character codes. */
  25.  
  26. STATIC struct { STRPTR Name; UBYTE Value; } CodeTab[] =
  27. {
  28.     {    "NUL",    0    },
  29.     {    "SOH",    1    },
  30.     {    "STX",    2    },
  31.     {    "ETX",    3    },
  32.     {    "EOT",    4    },
  33.     {    "ENQ",    5    },
  34.     {    "ACK",    6    },
  35.     {    "BEL",    7    },
  36.     {    "BS",    8    },
  37.     {    "HT",    9    },
  38.     {    "LF",    10    },
  39.     {    "VT",    11    },
  40.     {    "FF",    12    },
  41.     {    "CR",    13    },
  42.     {    "SO",    14    },
  43.     {    "SI",    15    },
  44.     {    "DLE",    16    },
  45.     {    "DC1",    17    },
  46.     {    "DC2",    18    },
  47.     {    "DC3",    19    },
  48.     {    "DC4",    20    },
  49.     {    "NAK",    21    },
  50.     {    "SYN",    22    },
  51.     {    "ETB",    23    },
  52.     {    "CAN",    24    },
  53.     {    "EM",    25    },
  54.     {    "SUB",    26    },
  55.     {    "ESC",    27    },
  56.     {    "FS",    28    },
  57.     {    "GS",    29    },
  58.     {    "RS",    30    },
  59.     {    "US",    31    },
  60.     {    "SP",    32    },
  61.     {    "DEL",    127    },
  62.     {    "SS2",    142    },
  63.     {    "SS3",    143    },
  64.     {    "DCS",    144    },
  65.     {    "CSI",    155    },
  66.     {    "ST",    156    },
  67.     {    "OSC",    157    },
  68.     {    "PM",    158    },
  69.     {    "APC",    159    },
  70.     {    "NBS",    160    },
  71.     {    "SHY",    173    }
  72. };
  73.  
  74.     /* TranslateSetup():
  75.      *
  76.      *    Set up for buffer translation.
  77.      */
  78.  
  79. VOID
  80. TranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  81. {
  82.     Handle->LocalBuffer            = NULL;
  83.     Handle->LocalLen            = 0;
  84.  
  85.     Handle->SourceBuffer        = SourceBuffer;
  86.     Handle->SourceLen            = SourceLen;
  87.  
  88.     Handle->DestinationBuffer    = DestinationBuffer;
  89.     Handle->DestinationLen        = DestinationLen;
  90.  
  91.     Handle->Table                = Table;
  92. }
  93.  
  94.     /* TranslateBuffer(struct TranslationHandle *Handle):
  95.      *
  96.      *    Translate buffer contents according to
  97.      *    translation table contents.
  98.      */
  99.  
  100. LONG
  101. TranslateBuffer(struct TranslationHandle *Handle)
  102. {
  103.     struct TranslationEntry    *Entry;
  104.     LONG BytesWritten;
  105.     STRPTR Data;
  106.  
  107.     Data = Handle->DestinationBuffer;
  108.     BytesWritten = 0;
  109.  
  110.         /* Are we to return any translated data? */
  111.  
  112.     while(Handle->LocalLen && BytesWritten < Handle->DestinationLen)
  113.     {
  114.             /* Decrement number of bytes in buffer. */
  115.  
  116.         Handle->LocalLen--;
  117.  
  118.             /* Return next character. */
  119.  
  120.         *Data++ = *Handle->LocalBuffer++;
  121.  
  122.             /* Add another byte. */
  123.  
  124.         BytesWritten++;
  125.     }
  126.  
  127.         /* Loop until done. */
  128.  
  129.     while(Handle->SourceLen && BytesWritten < Handle->DestinationLen)
  130.     {
  131.             /* Another byte eaten. */
  132.  
  133.         Handle->SourceLen--;
  134.  
  135.             /* Get table entry. */
  136.  
  137.         if(Entry = Handle->Table[*Handle->SourceBuffer++])
  138.         {
  139.                 /* Copy to local data area. */
  140.  
  141.             Handle->LocalBuffer    = Entry->String;
  142.             Handle->LocalLen    = Entry->Len;
  143.  
  144.                 /* Translate the data. */
  145.  
  146.             while(Handle->LocalLen && BytesWritten < Handle->DestinationLen)
  147.             {
  148.                     /* Decrement number of bytes in buffer. */
  149.  
  150.                 Handle->LocalLen--;
  151.  
  152.                     /* Return next character. */
  153.  
  154.                 *Data++ = *Handle->LocalBuffer++;
  155.  
  156.                     /* Add another byte. */
  157.  
  158.                 BytesWritten++;
  159.             }
  160.         }
  161.     }
  162.  
  163.     return(BytesWritten);
  164. }
  165.  
  166.     /* NameToCode(STRPTR Name):
  167.      *
  168.      *    Translate a symbolic character code name of numeral.
  169.      */
  170.  
  171. UBYTE
  172. NameToCode(STRPTR Name)
  173. {
  174.     LONG i;
  175.  
  176.     for(i = 0 ; i < NUM_ELEMENTS(CodeTab) ; i++)
  177.     {
  178.         if(!Stricmp(CodeTab[i].Name,Name))
  179.             return(CodeTab[i].Value);
  180.     }
  181.  
  182.     return((UBYTE)Atol(Name));
  183. }
  184.  
  185.     /* CodeToName(UBYTE Code):
  186.      *
  187.      *    Translate a character code into a symbolic
  188.      *    name or numeral.
  189.      */
  190.  
  191. STRPTR
  192. CodeToName(UBYTE Code)
  193. {
  194.     STATIC UBYTE Name[6];
  195.  
  196.     LONG i;
  197.  
  198.     for(i = 0 ; i < NUM_ELEMENTS(CodeTab) ; i++)
  199.     {
  200.         if(CodeTab[i].Value == Code)
  201.             return(CodeTab[i].Name);
  202.     }
  203.  
  204.     LimitedSPrintf(sizeof(Name),Name,"%03ld",Code);
  205.  
  206.     return(Name);
  207. }
  208.  
  209.     /* FreeTranslationTable(struct TranslationEntry **Table):
  210.      *
  211.      *    Free a character translation table.
  212.      */
  213.  
  214. VOID
  215. FreeTranslationTable(struct TranslationEntry **Table)
  216. {
  217.     LONG i;
  218.  
  219.     for(i = 0 ; i < 256 ; i++)
  220.     {
  221.         if(Table[i])
  222.             FreeTranslationEntry(Table[i]);
  223.     }
  224.  
  225.     FreeVecPooled(Table);
  226. }
  227.  
  228.     /* AllocTranslationTable():
  229.      *
  230.      *    Allocate a character translation table.
  231.      */
  232.  
  233. struct TranslationEntry **
  234. AllocTranslationTable()
  235. {
  236.     return((struct TranslationEntry **)AllocVecPooled(sizeof(struct TranslationEntry *) * 256,MEMF_ANY|MEMF_CLEAR));
  237. }
  238.  
  239.     /* FreeTranslationEntry(struct TranslationEntry *Entry):
  240.      *
  241.      *    Free a character translation table entry.
  242.      */
  243.  
  244. VOID
  245. FreeTranslationEntry(struct TranslationEntry *Entry)
  246. {
  247.     FreeVecPooled(Entry);
  248. }
  249.  
  250.     /* TranslateString(STRPTR From,STRPTR To):
  251.      *
  252.      *    Translate a string to contain control codes
  253.      *    into a string to contain the real codes.
  254.      */
  255.  
  256. LONG
  257. TranslateString(STRPTR From,STRPTR To)
  258. {
  259.     BOOL GotControl,GotEscape;
  260.     LONG Len,Count,i;
  261.  
  262.     GotControl    = FALSE;
  263.     GotEscape    = FALSE;
  264.  
  265.     Len        = strlen(From);
  266.     Count    = 0;
  267.  
  268.     for(i = 0 ; i < Len ; i++)
  269.     {
  270.         if(!GotControl && !GotEscape)
  271.         {
  272.             if(From[i] == '\\')
  273.             {
  274.                 GotControl = TRUE;
  275.  
  276.                 continue;
  277.             }
  278.  
  279.             if(From[i] == '^')
  280.             {
  281.                 GotEscape = TRUE;
  282.  
  283.                 continue;
  284.             }
  285.  
  286.             To[Count++] = From[i];
  287.         }
  288.         else
  289.         {
  290.             if(GotEscape)
  291.             {
  292.                 if(ToUpper(From[i]) >= 'A' && ToUpper(From[i]) <= '_')
  293.                     To[Count++] = ToUpper(From[i]) - '@';
  294.                 else
  295.                     To[Count++] = From[i];
  296.  
  297.                 GotEscape = FALSE;
  298.             }
  299.             else
  300.             {
  301.                 if(GotControl)
  302.                 {
  303.                     switch(ToUpper(From[i]))
  304.                     {
  305.                             /* These macro commands are plainly
  306.                              * ignored.
  307.                              */
  308.  
  309.                         case '0':
  310.                         case '1':
  311.                         case '2':
  312.                         case '3':
  313.                         case '4':
  314.                         case '5':
  315.                         case '6':
  316.  
  317.                             break;
  318.  
  319.                             /* These are macro commands and
  320.                              * not supported.
  321.                              */
  322.  
  323.                         case 'A':
  324.                         case 'C':
  325.                         case 'D':
  326.                         case 'G':
  327.                         case 'H':
  328.                         case 'I':
  329.                         case 'P':
  330.                         case 'U':
  331.                         case 'X':
  332.  
  333.                             To[Count++] = '\\';
  334.                             To[Count++] = From[i];
  335.                             break;
  336.  
  337.                             /* Translate code. */
  338.  
  339.                         case '*':
  340.  
  341.                             i++;
  342.  
  343.                             while(i < Len && From[i] == ' ')
  344.                                 i++;
  345.  
  346.                             if(i < Len)
  347.                             {
  348.                                 UBYTE DummyBuffer[5],j = 0,Char;
  349.  
  350.                                 if(From[i] >= '0' && From[i] <= '9')
  351.                                 {
  352.                                     while(j < 3 && i < Len)
  353.                                     {
  354.                                         Char = From[i++];
  355.  
  356.                                         if(Char >= '0' && Char <= '9')
  357.                                             DummyBuffer[j++] = Char;
  358.                                         else
  359.                                         {
  360.                                             i--;
  361.  
  362.                                             break;
  363.                                         }
  364.                                     }
  365.                                 }
  366.                                 else
  367.                                 {
  368.                                     while(j < 4 && i < Len)
  369.                                     {
  370.                                         Char = ToLower(From[i++]);
  371.  
  372.                                         if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  373.                                             DummyBuffer[j++] = Char;
  374.                                         else
  375.                                         {
  376.                                             i--;
  377.  
  378.                                             break;
  379.                                         }
  380.                                     }
  381.                                 }
  382.  
  383.                                 DummyBuffer[j] = 0;
  384.  
  385.                                 To[Count++] = NameToCode(DummyBuffer);
  386.                             }
  387.  
  388.                             i--;
  389.  
  390.                             break;
  391.  
  392.                             /* This is a backspace. */
  393.  
  394.                         case 'B':
  395.  
  396.                             To[Count++] = '\b';
  397.                             break;
  398.  
  399.                             /* This is a form feed. */
  400.  
  401.                         case 'F':
  402.  
  403.                             To[Count++] = '\f';
  404.                             break;
  405.  
  406.                             /* This is a line feed. */
  407.  
  408.                         case 'N':
  409.  
  410.                             To[Count++] = '\n';
  411.                             break;
  412.  
  413.                             /* This is a carriage return. */
  414.  
  415.                         case 'R':
  416.  
  417.                             To[Count++] = '\r';
  418.                             break;
  419.  
  420.                             /* This is a tab. */
  421.  
  422.                         case 'T':
  423.  
  424.                             To[Count++] = '\t';
  425.                             break;
  426.  
  427.                             /* Produce the escape character. */
  428.  
  429.                         case 'E':
  430.  
  431.                             To[Count++] = ESC;
  432.                             break;
  433.  
  434.                             /* Stuff the character into the buffer. */
  435.  
  436.                         default:
  437.  
  438.                             To[Count++] = From[i];
  439.                             break;
  440.                     }
  441.  
  442.                     GotControl = FALSE;
  443.                 }
  444.             }
  445.         }
  446.     }
  447.  
  448.     return(Count);
  449. }
  450.  
  451.     /* AllocTranslationEntry(STRPTR String):
  452.      *
  453.      *    Allocate a character translation table entry.
  454.      */
  455.  
  456. struct TranslationEntry *
  457. AllocTranslationEntry(STRPTR String)
  458. {
  459.     UBYTE LocalBuffer[256];
  460.     LONG Count;
  461.  
  462.     Count = TranslateString(String,LocalBuffer);
  463.  
  464.     if(Count > 0)
  465.     {
  466.         struct TranslationEntry *Entry;
  467.         UBYTE Type;
  468.  
  469.         if(Count > 1)
  470.         {
  471.             Type = TRANSLATE_STRING;
  472.  
  473.             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry) + Count + 1,MEMF_ANY|MEMF_CLEAR))
  474.             {
  475.                 Entry->String = (STRPTR)(Entry + 1);
  476.  
  477.                 CopyMem(LocalBuffer,Entry->String,Count);
  478.             }
  479.         }
  480.         else
  481.         {
  482.             Type = TRANSLATE_SINGLE;
  483.  
  484.             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  485.             {
  486.                 Entry->String    = &Entry->Extra;
  487.                 Entry->Extra    = LocalBuffer[0];
  488.             }
  489.         }
  490.  
  491.         if(Entry)
  492.         {
  493.             Entry->Type    = Type;
  494.             Entry->Len    = Count;
  495.  
  496.             return(Entry);
  497.         }
  498.     }
  499.  
  500.     return(NULL);
  501. }
  502.  
  503.     /* FillTranslationTable(struct TranslationEntry **Table):
  504.      *
  505.      *    Fill the translation table with defaults.
  506.      */
  507.  
  508. BOOL
  509. FillTranslationTable(struct TranslationEntry **Table)
  510. {
  511.     BOOL Success;
  512.     LONG i;
  513.  
  514.     Success = TRUE;
  515.  
  516.     for(i = 0 ; Success && i < 256 ; i++)
  517.     {
  518.         if(Table[i] = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  519.         {
  520.             Table[i]->Type        = TRANSLATE_SINGLE;
  521.             Table[i]->String    = &Table[i]->Extra;
  522.             Table[i]->Extra        = i;
  523.             Table[i]->Len        = 1;
  524.         }
  525.         else
  526.             Success = FALSE;
  527.     }
  528.  
  529.     if(!Success)
  530.     {
  531.         for(i = 0 ; i < 256 ; i++)
  532.         {
  533.             FreeVecPooled(Table[i]);
  534.             Table[i] = NULL;
  535.         }
  536.     }
  537.  
  538.     return(Success);
  539. }
  540.  
  541.     /* IsStandardTable(struct TranslationEntry **Table):
  542.      *
  543.      *    Checks a translation table to see if it contains
  544.      *    standard data.
  545.      */
  546.  
  547. BOOL
  548. IsStandardTable(struct TranslationEntry **Table)
  549. {
  550.     LONG i;
  551.  
  552.     for(i = 0 ; i < 256 ; i++)
  553.     {
  554.         if(Table[i])
  555.         {
  556.             if(Table[i]->Type != TRANSLATE_SINGLE || Table[i]->Len != 1 || Table[i]->String[0] != i)
  557.                 return(FALSE);
  558.         }
  559.         else
  560.             return(FALSE);
  561.     }
  562.  
  563.     return(TRUE);
  564. }
  565.  
  566.     /* TranslateBack(STRPTR From,LONG Len,STRPTR To):
  567.      *
  568.      *    Translate a precompiled translation string
  569.      *    back.
  570.      */
  571.  
  572. VOID
  573. TranslateBack(STRPTR From,LONG Len,STRPTR To,LONG ToLen)
  574. {
  575.     STATIC BYTE TypeTable[256] =
  576.     {
  577.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 ,'b','t','n', 1 ,'f','r', 1 , 1,
  578.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 , 1 , 1 , 1 ,'e', 1 , 1 , 1 , 1,
  579.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  580.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  581.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  582.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 ,'\\',2 , 2 , 2,
  583.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  584.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0,
  585.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  586.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  587.          0 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 2,
  588.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  589.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  590.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  591.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  592.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2
  593.     };
  594.  
  595.     STRPTR Buffer;
  596.     LONG i,j,BufLen;
  597.  
  598.     for(i = j = 0 ; i < Len ; i++)
  599.     {
  600.         switch(TypeTable[From[i]])
  601.         {
  602.             case 0:
  603.  
  604.                 Buffer = CodeToName(From[i]);
  605.  
  606.                 BufLen = strlen(Buffer);
  607.  
  608.                 if(j + 2 + BufLen >= ToLen)
  609.                     break;
  610.  
  611.                 To[j++] = '\\';
  612.                 To[j++] = '*';
  613.  
  614.                 CopyMem(Buffer,&To[j],BufLen);
  615.  
  616.                 j += BufLen;
  617.  
  618.                 break;
  619.  
  620.             case 1:
  621.  
  622.                 if(j + 2 >= ToLen)
  623.                     break;
  624.  
  625.                 To[j++] = '^';
  626.                 To[j++] = From[i] + '@';
  627.                 break;
  628.  
  629.             case 2:
  630.  
  631.                 if(j + 1 >= ToLen)
  632.                     break;
  633.  
  634.                 To[j++] = From[i];
  635.                 break;
  636.  
  637.             default:
  638.  
  639.                 if(j + 2 >= ToLen)
  640.                     break;
  641.  
  642.                 To[j++] = '\\';
  643.                 To[j++] = TypeTable[From[i]];
  644.                 break;
  645.         }
  646.     }
  647.  
  648.     To[j] = 0;
  649. }
  650.  
  651.     /* SaveTranslationTables():
  652.      *
  653.      *    Save a character translation table to a file.
  654.      */
  655.  
  656. BOOL
  657. SaveTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  658. {
  659.     LONG Error,i;
  660.     BOOL DoIt;
  661.  
  662.     DoIt = FALSE;
  663.  
  664.     for(i = 0 ; !DoIt && i < 256 ; i++)
  665.     {
  666.         if(SendTable[i] || ReceiveTable[i])
  667.             DoIt = TRUE;
  668.     }
  669.  
  670.     Error = 0;
  671.  
  672.     if(DoIt)
  673.     {
  674.         struct IFFHandle *Handle;
  675.         UBYTE MasterTable[256];
  676.  
  677.         for(i = 0 ; i < 256 ; i++)
  678.         {
  679.             if(SendTable[i])
  680.             {
  681.                 if(SendTable[i]->Type == TRANSLATE_SINGLE && SendTable[i]->Len == 1 && SendTable[i]->String[0] == i)
  682.                     MasterTable[i] = TRANSLATION_VERBATIM;
  683.                 else
  684.                     MasterTable[i] = TRANSLATION_OTHER;
  685.             }
  686.             else
  687.                 MasterTable[i] = TRANSLATION_IGNORE;
  688.  
  689.             if(ReceiveTable[i])
  690.             {
  691.                 if(ReceiveTable[i]->Type == TRANSLATE_SINGLE && ReceiveTable[i]->Len == 1 && ReceiveTable[i]->String[0] == i)
  692.                     MasterTable[i] |= TRANSLATION_VERBATIM << 4;
  693.                 else
  694.                     MasterTable[i] |= TRANSLATION_OTHER << 4;
  695.             }
  696.             else
  697.                 MasterTable[i] |= TRANSLATION_IGNORE << 4;
  698.         }
  699.  
  700.         if(!(Handle = OpenIFFStream(Name,MODE_NEWFILE)))
  701.             Error = IoErr();
  702.         else
  703.         {
  704.             if(!(Error = PushChunk(Handle,ID_TERM,ID_CAT,IFFSIZE_UNKNOWN)))
  705.             {
  706.                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  707.                 {
  708.                     if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  709.                     {
  710.                         struct TermInfo TermInfo;
  711.  
  712.                         TermInfo.Version    = CONFIG_FILE_VERSION;
  713.                         TermInfo.Revision    = CONFIG_FILE_REVISION;
  714.  
  715.                         if(WriteChunkRecords(Handle,&TermInfo,sizeof(struct TermInfo),1) != 1)
  716.                             Error = IoErr();
  717.  
  718.                         if(!Error)
  719.                             Error = PopChunk(Handle);
  720.                     }
  721.  
  722.                     if(!Error)
  723.                     {
  724.                         if(!(Error = PushChunk(Handle,0,ID_TRNS,256)))
  725.                         {
  726.                             if(WriteChunkBytes(Handle,MasterTable,256) != 256)
  727.                                 Error = IoErr();
  728.  
  729.                             if(!Error)
  730.                                 Error = PopChunk(Handle);
  731.                         }
  732.                     }
  733.  
  734.                     if(!Error)
  735.                         Error = PopChunk(Handle);
  736.                 }
  737.  
  738.                 if(!Error)
  739.                 {
  740.                     struct TranslationHeader Header;
  741.  
  742.                     for(i = 0 ; !Error && i < 256 ; i++)
  743.                     {
  744.                         Header.Code    = i;
  745.                         Header.Pad    = 0;
  746.  
  747.                         if(SendTable[i] && (MasterTable[i] & 0xF) == TRANSLATION_OTHER)
  748.                         {
  749.                             Header.Type    = SendTable[i]->Type;
  750.                             Header.Len    = SendTable[i]->Len;
  751.  
  752.                             if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  753.                             {
  754.                                 if(!(Error = PushChunk(Handle,0,ID_SEND,sizeof(struct TranslationHeader))))
  755.                                 {
  756.                                     if(WriteChunkRecords(Handle,&Header,sizeof(struct TranslationHeader),1) != 1)
  757.                                         Error = IoErr();
  758.  
  759.                                     if(!Error)
  760.                                         Error = PopChunk(Handle);
  761.                                 }
  762.  
  763.                                 if(!Error)
  764.                                 {
  765.                                     if(!(Error = PushChunk(Handle,0,ID_CHRS,SendTable[i]->Len)))
  766.                                     {
  767.                                         if(WriteChunkRecords(Handle,SendTable[i]->String,SendTable[i]->Len,1) != 1)
  768.                                             Error = IoErr();
  769.  
  770.                                         if(!Error)
  771.                                             Error = PopChunk(Handle);
  772.                                     }
  773.                                 }
  774.  
  775.                                 if(!Error)
  776.                                     Error = PopChunk(Handle);
  777.                             }
  778.                         }
  779.  
  780.                         if(ReceiveTable[i] && (MasterTable[i] >> 4) == TRANSLATION_OTHER)
  781.                         {
  782.                             Header.Type    = ReceiveTable[i]->Type;
  783.                             Header.Len    = ReceiveTable[i]->Len;
  784.  
  785.                             if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  786.                             {
  787.                                 if(!(Error = PushChunk(Handle,0,ID_RECV,sizeof(struct TranslationHeader))))
  788.                                 {
  789.                                     if(WriteChunkRecords(Handle,&Header,sizeof(struct TranslationHeader),1) != 1)
  790.                                         Error = IoErr();
  791.  
  792.                                     if(!Error)
  793.                                         Error = PopChunk(Handle);
  794.                                 }
  795.  
  796.                                 if(!Error)
  797.                                 {
  798.                                     if(!(Error = PushChunk(Handle,0,ID_CHRS,ReceiveTable[i]->Len)))
  799.                                     {
  800.                                         if(WriteChunkRecords(Handle,ReceiveTable[i]->String,ReceiveTable[i]->Len,1) != 1)
  801.                                             Error = IoErr();
  802.  
  803.                                         if(!Error)
  804.                                             Error = PopChunk(Handle);
  805.                                     }
  806.                                 }
  807.  
  808.                                 if(!Error)
  809.                                     Error = PopChunk(Handle);
  810.                             }
  811.                         }
  812.                     }
  813.                 }
  814.  
  815.                 if(!Error)
  816.                     Error = PopChunk(Handle);
  817.             }
  818.  
  819.             CloseIFFStream(Handle);
  820.         }
  821.     }
  822.  
  823.     if(Error)
  824.     {
  825.         SetIoErr(Error);
  826.         return(FALSE);
  827.     }
  828.     else
  829.         return(TRUE);
  830. }
  831.  
  832.     /* LoadTranslationTables():
  833.      *
  834.      *    Load a translation table from a file.
  835.      */
  836.  
  837. BOOL
  838. LoadTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  839. {
  840.     STATIC ULONG Stops[5 * 2] =
  841.     {
  842.         ID_TERM,    ID_VERS,
  843.         ID_TERM,    ID_TRNS,
  844.         ID_TERM,    ID_SEND,
  845.         ID_TERM,    ID_RECV,
  846.         ID_TERM,    ID_CHRS
  847.     };
  848.  
  849.     struct IFFHandle *Handle;
  850.     UBYTE MasterTable[256];
  851.     BOOL GotMasterTable;
  852.     BOOL Success;
  853.     LONG Error;
  854.     LONG i;
  855.  
  856.     GotMasterTable = FALSE;
  857.     Success = FALSE;
  858.  
  859.     if(Handle = OpenIFFStream(Name,MODE_OLDFILE))
  860.     {
  861.         if(!(Error = StopChunks(Handle,(LONG *)Stops,5)))
  862.         {
  863.             struct TranslationHeader Header;
  864.             struct ContextNode *Chunk;
  865.             struct TermInfo TermInfo;
  866.             LONG LastType;
  867.  
  868.             LastType = TYPE_NONE;
  869.             Success = TRUE;
  870.  
  871.             while(Success && !ParseIFF(Handle,IFFPARSE_SCAN))
  872.             {
  873.                 Chunk = CurrentChunk(Handle);
  874.  
  875.                 switch(Chunk->cn_ID)
  876.                 {
  877.                     case ID_VERS:
  878.  
  879.                         if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  880.                         {
  881.                             if(TermInfo.Version > CONFIG_FILE_VERSION || (TermInfo.Version == CONFIG_FILE_VERSION && TermInfo.Revision > CONFIG_FILE_REVISION))
  882.                             {
  883.                                 Error = ERR_OUTDATED;
  884.  
  885.                                 Success = FALSE;
  886.                             }
  887.                         }
  888.                         else
  889.                         {
  890.                             Error = IoErr();
  891.  
  892.                             Success = FALSE;
  893.                         }
  894.  
  895.                         break;
  896.  
  897.                     case ID_TRNS:
  898.  
  899.                         if(ReadChunkBytes(Handle,MasterTable,256) == 256)
  900.                             GotMasterTable = TRUE;
  901.                         else
  902.                         {
  903.                             Error = IoErr();
  904.  
  905.                             Success = FALSE;
  906.                         }
  907.  
  908.                         break;
  909.  
  910.                     case ID_SEND:
  911.  
  912.                         if(LastType != TYPE_NONE)
  913.                             Success = FALSE;
  914.                         else
  915.                         {
  916.                             if(!ReadChunkRecords(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk->cn_Size),1))
  917.                             {
  918.                                 Error = IoErr();
  919.  
  920.                                 Success = FALSE;
  921.                             }
  922.                             else
  923.                                 LastType = TYPE_SEND;
  924.                         }
  925.  
  926.                         break;
  927.  
  928.                     case ID_RECV:
  929.  
  930.                         if(LastType != TYPE_NONE)
  931.                         {
  932.                             Error = IFFERR_MANGLED;
  933.  
  934.                             Success = FALSE;
  935.                         }
  936.                         else
  937.                         {
  938.                             if(!ReadChunkRecords(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk->cn_Size),1))
  939.                             {
  940.                                 Success = FALSE;
  941.  
  942.                                 Error = IoErr();
  943.                             }
  944.                             else
  945.                                 LastType = TYPE_RECEIVE;
  946.                         }
  947.  
  948.                         break;
  949.  
  950.                     case ID_CHRS:
  951.  
  952.                         if(LastType == TYPE_NONE)
  953.                         {
  954.                             Error = IFFERR_MANGLED;
  955.  
  956.                             Success = FALSE;
  957.                         }
  958.                         else
  959.                         {
  960.                             UBYTE LocalBuffer[256];
  961.  
  962.                             if(ReadChunkRecords(Handle,LocalBuffer,Header.Len,1))
  963.                             {
  964.                                 struct TranslationEntry *Entry;
  965.  
  966.                                 if(Header.Type == TRANSLATE_SINGLE)
  967.                                 {
  968.                                     if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  969.                                     {
  970.                                         Entry->String    = &Entry->Extra;
  971.                                         Entry->Extra    = LocalBuffer[0];
  972.                                     }
  973.                                 }
  974.                                 else
  975.                                 {
  976.                                     if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry) + Header.Len + 1,MEMF_ANY|MEMF_CLEAR))
  977.                                     {
  978.                                         Entry->String = (STRPTR)(Entry + 1);
  979.  
  980.                                         CopyMem(LocalBuffer,Entry->String,Header.Len);
  981.                                     }
  982.                                 }
  983.  
  984.                                 if(Entry)
  985.                                 {
  986.                                     Entry->Type    = Header.Type;
  987.                                     Entry->Len    = Header.Len;
  988.  
  989.                                     if(LastType == TYPE_SEND)
  990.                                         SendTable[Header.Code] = Entry;
  991.                                     else
  992.                                         ReceiveTable[Header.Code] = Entry;
  993.  
  994.                                     LastType = TYPE_NONE;
  995.                                 }
  996.                                 else
  997.                                 {
  998.                                     Error = ERROR_NO_FREE_STORE;
  999.  
  1000.                                     Success = FALSE;
  1001.                                 }
  1002.                             }
  1003.                             else
  1004.                             {
  1005.                                 Error = IoErr();
  1006.  
  1007.                                 Success = FALSE;
  1008.                             }
  1009.                         }
  1010.  
  1011.                         break;
  1012.                 }
  1013.             }
  1014.         }
  1015.  
  1016.         CloseIFFStream(Handle);
  1017.     }
  1018.     else
  1019.         Error = IoErr();
  1020.  
  1021.     if(Success && GotMasterTable)
  1022.     {
  1023.         struct TranslationEntry *Entry;
  1024.  
  1025.         for(i = 0 ; i < 256 ; i++)
  1026.         {
  1027.             if((MasterTable[i] & 0xF) == TRANSLATION_VERBATIM)
  1028.             {
  1029.                 if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  1030.                 {
  1031.                     Entry->Type        = TRANSLATE_SINGLE;
  1032.                     Entry->String    = &Entry->Extra;
  1033.                     Entry->Extra    = i;
  1034.                     Entry->Len        = 1;
  1035.  
  1036.                     SendTable[i] = Entry;
  1037.                 }
  1038.                 else
  1039.                 {
  1040.                     Error = ERROR_NO_FREE_STORE;
  1041.  
  1042.                     Success = FALSE;
  1043.  
  1044.                     break;
  1045.                 }
  1046.             }
  1047.  
  1048.             if((MasterTable[i] >> 4) == TRANSLATION_VERBATIM)
  1049.             {
  1050.                 if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  1051.                 {
  1052.                     Entry->Type        = TRANSLATE_SINGLE;
  1053.                     Entry->String    = &Entry->Extra;
  1054.                     Entry->Extra    = i;
  1055.                     Entry->Len        = 1;
  1056.  
  1057.                     ReceiveTable[i] = Entry;
  1058.                 }
  1059.                 else
  1060.                 {
  1061.                     Error = ERROR_NO_FREE_STORE;
  1062.  
  1063.                     Success = FALSE;
  1064.  
  1065.                     break;
  1066.                 }
  1067.             }
  1068.         }
  1069.     }
  1070.  
  1071.     if(!Success)
  1072.     {
  1073.         for(i = 0 ; i < 256 ; i++)
  1074.         {
  1075.             if(SendTable[i])
  1076.             {
  1077.                 FreeTranslationEntry(SendTable[i]);
  1078.  
  1079.                 SendTable[i] = NULL;
  1080.             }
  1081.  
  1082.             if(ReceiveTable[i])
  1083.             {
  1084.                 FreeTranslationEntry(ReceiveTable[i]);
  1085.  
  1086.                 ReceiveTable[i] = NULL;
  1087.             }
  1088.         }
  1089.     }
  1090.  
  1091.     if(Error)
  1092.         SetIoErr(Error);
  1093.  
  1094.     return(Success);
  1095. }
  1096.  
  1097.     /* LoadDefaultTranslationTables(STRPTR FileName):
  1098.      *
  1099.      *    Load the default character translation file.
  1100.      */
  1101.  
  1102. BOOL
  1103. LoadDefaultTranslationTables(STRPTR FileName)
  1104. {
  1105.     BOOL Success;
  1106.  
  1107.     Success = FALSE;
  1108.  
  1109.     if(SendTable = AllocTranslationTable())
  1110.     {
  1111.         if(ReceiveTable = AllocTranslationTable())
  1112.         {
  1113.             BOOL ReleaseIt;
  1114.  
  1115.             if(LoadTranslationTables(FileName,SendTable,ReceiveTable))
  1116.             {
  1117.                 ReleaseIt = (BOOL)(IsStandardTable(SendTable) && IsStandardTable(ReceiveTable));
  1118.  
  1119.                 Success = TRUE;
  1120.             }
  1121.             else
  1122.                 ReleaseIt = TRUE;
  1123.  
  1124.             if(ReleaseIt)
  1125.             {
  1126.                 FreeTranslationTable(SendTable);
  1127.                 SendTable = NULL;
  1128.  
  1129.                 FreeTranslationTable(ReceiveTable);
  1130.                 ReceiveTable = NULL;
  1131.             }
  1132.         }
  1133.         else
  1134.         {
  1135.             FreeTranslationTable(SendTable);
  1136.             SendTable = NULL;
  1137.         }
  1138.     }
  1139.  
  1140.     return(Success);
  1141. }
  1142.